import { BaseControl } from './BaseControl';
import { FormControl } from './FormControl';
import { FormGroupData, FormItems, GroupError, updateChangeFn } from './form.interface';
import { FormArray } from './FormArray';
import { FormUtils } from './FormUtils';
import { Utils } from '../utils';



export class FormGroup extends BaseControl {

	constructor(formItems: FormItems) {
		super();

		for (const key in formItems) {
			const formItem = formItems[key];
			const isFormControl = formItem instanceof FormControl;
			const isFormArray = formItem instanceof FormArray;
			const isFormGroup = formItem instanceof FormGroup;

			if (isFormControl) {
				const formControl = formItem;
				this.addControl(key, formControl);
			}

			if (isFormGroup) {
				const formGroup = formItem;
				this.addGroup(key, formGroup);
			}

			if (isFormArray) {
				const formArray = formItem;
				this.addArray(key, formArray);
			}
		}

		this.randomId = Utils.getRandomChars(16);
	}
	/**
	 * @description FormGroup包含的FormControl | FormArray | FormGroup  只读
	 */
	private _controls: { [key: string]: FormControl | FormArray | FormGroup } = {};
	public get controls() {
		return this.getControls();
	}

	public getControls = () => {
		return this._controls;
	}
	/**
	 * @description 添加一个FormControl
	 * @param {string}  name FormControlName
	 * @param {FormControl}  formControl
	 */
	public addControl = (name: string, formControl: FormControl) => {
		formControl.parent = this;
		this._controls[name] = formControl;
		this.onCollectionChange();
		return this;
	};
	public addGroup = (name: string, formGroup: FormGroup) => {
		formGroup.parent = this;
		this._controls[name] = formGroup;
		this.onCollectionChange();
		return this;
	};
	public addArray = (name: string, formArray: FormArray) => {
		formArray.parent = this;
		this._controls[name] = formArray;
		this.onCollectionChange();
		return this;
	};
	/**
	 * @description 保留指定的name，其他的清除掉。
	 * @param {Array<string>}  names 需要保留的 name
	 */
	public retain = (names: Array<string>) => {
		for (const key in this._controls) {
			const include = names.includes(key);
			if (include === false) {
				this.remove(key);
			}
		}
		this.onCollectionChange();
		return this;
	};

	public remove = (name: string) => {
		delete this._controls[name];
		this.onCollectionChange();
		return this;
	};
	/**
	 * @description 清空 controls
	 */
	public clear = () => {
		this._controls = {};
		this.onCollectionChange();
		return this;
	};
	/**  this._controls 返回一个新数组 */
	public update = () => {
		this._controls = { ...this._controls };
		this.onCollectionChange();
		this._runUpdateChangeCallbacks();
		for(let key in this._controls){
			this._controls[key].update();
		}
		return this._controls;
	};
	/** updata改变，回调函数 */
	private _updateChangeCallbacks: Array<updateChangeFn> = [];
	/** 设置，updata改变，回调函数 */
	public updateChange = (callback: updateChangeFn) => {
		if (Utils.isFunction(callback)) {
			this._updateChangeCallbacks.push(callback);
		}
	};
	/** 运行，updata改变，回调函数 */
	private _runUpdateChangeCallbacks = () => {
		this._updateChangeCallbacks.forEach((callback) => {
			callback();
		});
	};
	/**
	 * @description FormGroup的值，FormGroup所包含formControl值得集合
	 */
	private _value: any = {};
	public get value() {
		this._updateValue();
		return { ...this._value };
	}
	/**
	 * @description 更新FormGroup的value
	 */
	private _updateValue = () => {
		const result: { [key: string]: any } = {};
		for (const name in this._controls) {
			const formItem = this._controls[name];
			const formItemValue = formItem.value;
			// if (formItem.disable() === false) {
			// 	result[name] = formItemValue;
			// }
			if (FormUtils.isFormControl(formItem)) {
				if ((formItem as FormControl).disabled === false) {
					result[name] = formItemValue;
				}
			} else {
				result[name] = formItemValue;
			}

		}
		this._value = result;
		this.runValueChangeCallbacks(this._value);
		return this._value;
	};
	/** formGroup 扁平的 value
	 * {
	 * 		'1' : {a:1}
	 * 		'a' : {b:2}
	 * }
	 * => 
	 * {
	 * 		a: 1,
	 * 		b: 2
	 * }
	 */
	private _flatValue: any = {};
	/** 获取扁平value */
	public get flatValue() {
		this._updateFlatValue();
		return { ...this._flatValue };
	}

	private _updateFlatValue = () => {
		let result: { [key: string]: any } = {};
		for (const name in this._controls) {
			const formItem = this._controls[name];
			const formItemValue = formItem.value;

			const isFormGroup = FormUtils.isFormGroup(formItem);
			const isFormControl = FormUtils.isFormControl(formItem);

			if (isFormControl) {
				result[name] = formItemValue;
			} else if (isFormGroup) {
				const groupValue = formItem.value;
				result = { ...result, ...groupValue };
			}
		}
		this._flatValue = result;;
		return this._flatValue;
	};

	/** 脏值 */
	public get dirtyValue() {
		const result: { [key: string]: any } = {};
		for (const name in this._controls) {
			const formItem = this._controls[name];
			const formItemValue = formItem.value;
			if (formItem.dirty) {
				if (FormUtils.isFormControl(formItem)) {
					if ((formItem as FormControl).disabled === false) {
						result[name] = formItemValue;
					}
				} else {
					result[name] = formItemValue;
				}
			}
		}
		return result;
	}




	/**
	 * @description 通过 formControlName 获取formControl
	 */
	public getControl = (name: string): FormControl | undefined => {
		const formControl = this._controls[name];
		const isFormControl = formControl instanceof FormControl;
		return isFormControl ? formControl : undefined;
	};

	public getGroup = (name: string) => {
		const formGroup = this._controls[name];
		const isFormGroup = formGroup instanceof FormGroup;
		return isFormGroup ? formGroup : undefined;
	};

	public getArray = (name: string) => {
		const formArray = this._controls[name];
		const isFormArray = formArray instanceof FormArray;
		return isFormArray ? formArray : undefined;
	};
	/**
	 * @description 验证结果 只读 boolean
	 */
	private _valid = true;
	public get valid() {
		this._updateValid();
		return this._valid;
	}


	private _updateValid = () => {

		const errors: GroupError[] = [];
		// 上次验证结果
		const provValid = this._valid;
		this._valid = true;
		for (const name in this._controls) {
			const formItem = this._controls[name];
			const valid = formItem.valid;
			if (valid === false) {
				this._valid = false;
				const errorKey = name;
				const error: GroupError = {
					errorKey,
					errorItem: formItem,
				};
				errors.push(error);
			}
		}
		this._errors = errors;
		// this._validators.forEach((validatorFn)=>{
		// 	const validRes = validatorFn();
		// });
		if (provValid !== this._valid) {
			this.runValidChangeCallbacks(this._valid);
		}
	};

	/**
	 * 脏值
	 */
	private _dirty = false;
	public get dirty() {
		this._updateDirty();
		return this._dirty;
	}
	public set dirty(val: boolean) {
		if (val === false) {
			for (let key in this._controls) {
				const formItem = this._controls[key];
				if (FormUtils.isFormControl(formItem)) {
					const item = formItem as FormControl;
					item.dirty = false;
				}
			}
		}
	}
	private _updateDirty = () => {
		// 上次结果
		const provDirty = this._dirty;
		this._dirty = false;
		for (const name in this._controls) {
			const formItem = this._controls[name];
			const dirty = formItem.dirty;
			if (dirty === true) {
				this._dirty = true;
			}
		}
		// 是否发生改变
		const isChanged = provDirty !== this._dirty;
		if (isChanged) {
			this.runDirtyChangeCallbacks(this._dirty);
		}
	};
	/**
	 * @description 重置
	 */
	public reset = () => {
		for (const name in this._controls) {
			const formItem = this._controls[name];
			formItem.reset();
		}
	};


	private _errors: GroupError[] = [];
	public get errors() {
		return this._errors;
	}

	/** 显示错误 */
	public showErrors = () => {};

	/** 设置只读 */
	public set readonly(val: boolean) {
		for (const key in this._controls) {
			const formItem = this._controls[key];
			
			if(formItem.readonlyException === false){
				formItem.readonly = val;
				// console.log(formItem);
			}
			
		}
	};
	/** 只读 */
	public get readonly() {
		const formItems: (FormControl | FormArray | FormGroup)[] = [];
		for (const key in this._controls) {
			const item = this._controls[key];
			if(item.readonlyException === false){
				formItems.push(item);
			}
		}
		let result = formItems.every(item=>item.readonly === true);
		return result;
	};


	/**
	 * @description 当内部元素发生改变时。
	 */
	public onCollectionChange = () => {
		this._updateValue();
		this._updateValid();
		this._updateDirty();
		if (this.parent) {
			this.parent.onCollectionChange();
		}
	};

	/** 自定义提交表单前验证 */
	public beforeSubmit = (): boolean => true;


	/** 唯一id */
	public randomId: string = '';

	/** formGroup 的数据 */
	public groupData: FormGroupData = {};

}